package com.itheima.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.mapper.EmpExprMapper;
import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.*;
import com.itheima.service.EmpLogService;
import com.itheima.service.EmpService;
import com.itheima.utils.CurrentHolder;
import com.itheima.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/*
员工信息的业务层实现类
 */
@Service//将类标记为 Spring 的 Bean，交给 Spring 容器管理。
// Spring 容器管理它是一个特殊的 @Component，用于表示服务层的类。
//@Component和@Service注解的区别是@Component是一个泛化的概念，而@Service是一个特殊的@Component，用于服务层的类。
public class EmpServiceImpl implements EmpService {

    @Autowired
    private EmpMapper empMapper;

    @Autowired
    private EmpExprMapper empExprMapper;

    @Autowired
    private EmpLogService empLogService;
        /*
        原始方式实现分页查询
        */
//    @Override
//    public PageResult page(Integer page, Integer pageSize) {
//        //1. 获取总记录数
//        Long total = empMapper.count();
//
//        //2. 获取结果列表
//        Integer start = (page - 1) * pageSize;
//        List<Emp> empList = empMapper.list(start, pageSize);
//
//        //3. 封装结果
//        return new PageResult(total, empList);
//    }


//    @Override
//public PageResult page(Integer page, Integer pageSize,String name, Integer gender, LocalDate begin, LocalDate end) {
//    //1. 设置分页参数
//    PageHelper.startPage(page,pageSize);
//
//    //2. 执行查询
//    List<Emp> empList = empMapper.list(name, gender, begin, end);
//
//
//    //3. 封装分页结果
//    Page<Emp> p = (Page<Emp>) empList;
//    //为什么要强转为Page<Emp>呢？因为Page<Emp>中有很多分页相关的信息，如总记录数等。
//    return new PageResult(p.getTotal(), p.getResult());
//    //p.getResult()获取当前页的结果集是一个List
//    }

    /*
    * 优化后的分页查询
     */
     @Override
    public PageResult page(EmpQueryParam empQueryParam) {
    //1. 设置分页参数
    PageHelper.startPage(empQueryParam.getPage(),empQueryParam.getPageSize());

    //2. 执行查询
    List<Emp> empList = empMapper.list(empQueryParam);


    //3. 封装分页结果
    Page<Emp> p = (Page<Emp>) empList;
    //为什么要强转为Page<Emp>呢？因为Page<Emp>中有很多分页相关的信息，如总记录数等。
    return new PageResult(p.getTotal(), p.getResult());
    //p.getResult()获取当前页的结果集是一个List
    }



    //一般只有出现RuntimeException异常时事务才会回滚，需要添加属性rollbackFor = Exception.class才能所有异常都回滚
    //事务传播行为：指的就是当一个事务方法被另一个事务方法调用时，这个事务方法应该如何进行事务控制。
    // 这里指的是添加员工信息和添加日志记录两个方法的事务控制。
    //研究两个方法都要被事务控制，事务的注解要加在service层的方法上，所以下方是调用service层的方法时，而不是调用mapper层的方法。

    //添加员工信息
    @Transactional(rollbackFor = Exception.class)//注解位置：业务（service）层的方法上、类上、接口上
    @Override
    public void save(Emp emp) {
        try {
            //1.补全基础属性
            emp.setCreateTime(LocalDateTime.now());
            emp.setUpdateTime(LocalDateTime.now());

            //2.保存员工基本信息

            empMapper.insert(emp);
            //调用完这个方法后，emp对象的id属性通过主键回填的方式，会被赋值为插入的记录的主键值

            //3.保存员工工作经历信息
            Integer empId = emp.getId();
            List<EmpExpr> exprList = emp.getExprList();
            //属性名是exprList生成的getExprList()方法
            if(!CollectionUtils.isEmpty(exprList)){

                exprList.forEach(empExpr -> empExpr.setEmpId(empId));
                empExprMapper.insertBatch(exprList);
    // 这里用到Mybatis中的动态SQL里提供的 <foreach> 标签，改标签的作用，是用来遍历循环

            }
        } finally {
            //这里可以添加日志记录
            EmpLog empLog = new EmpLog(null,LocalDateTime.now(),"新增员工"+emp);
            empLogService.insertLog(empLog);
        }
    }

    /*
    查询所有员工信息没有输入条件的查询
     */
    @Override
    public List<Emp> Getlist() {
        return empMapper.Getlist();
    }

    //批量删除员工信息
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteByIds(List<Integer> ids) {
        //1.根据ID批量删除员工基本信息
        empMapper.deleteByIds(ids);

        //2.根据员工的ID批量删除员工的工作经历信息
        empExprMapper.deleteByEmpIds(ids);
    }

    //根据ID查询员工的详细信息
    @Override
    public Emp GetInfo(Integer id) {
        return empMapper.getById(id);

    }

    //更新员工信息
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void update(Emp emp) {
        //1.根据Id更新员工基本信息
        emp.setUpdateTime(LocalDateTime.now());
        empMapper.updateById(emp);

        //2. 根据员工ID删除员工的工作经历信息 【删除老的】
        empExprMapper.deleteByEmpIds(Arrays.asList(emp.getId()));

        //3. 保存员工的工作经历信息 【保存新的】
        Integer empId = emp.getId();
        List<EmpExpr> exprList = emp.getExprList();
        if(!CollectionUtils.isEmpty(exprList))
        {
            //empExpr是遍历exprList的每一个元素 empExpr.setEmpId(empId)为每一个元素设置empId目的是要和empId关联起来
            exprList.forEach(empExpr -> empExpr.setEmpId(empId));
            empExprMapper.insertBatch(exprList);
        }
    }
    //登录方法
    @Override
    public LoginInfo login(Emp emp) {
        //1.根据用户名和密码查询员工信息
        Emp empLogin = empMapper.getUsernameAndPassword(emp);
        if(empLogin!=null){
            //1.生成JWT令牌
            Map<String,Object> dataMap = new HashMap<>();
            dataMap.put("id", empLogin.getId());
            dataMap.put("usename", empLogin.getUsername());


            String jwt = JwtUtils.generateToken(dataMap);//生成JWT令牌 后续的每一次请求当中，都会将这个令牌携带到服务端。
            LoginInfo loginInfo = new LoginInfo(empLogin.getId(),emp.getUsername(), empLogin.getName(),jwt);
            //2.返回登录成功的结果给前端
            return loginInfo;
        }
        return null;
    }

    //修改密码
    @Override
    public void changePwd(ChangePwd changePwd) {
        //通过threadLocal获取当前登录员工的ID
        Integer empId = CurrentHolder.getCurrentId();
        //根据员工ID查询员工信息
        Emp emp = empMapper.getById(empId);
        //判断旧密码是否正确
        if(!emp.getPassword().equals(changePwd.getOldPwd())){
            throw new RuntimeException("旧密码不正确");
        }
        //修改密码
        empMapper.updatePwd(empId, changePwd.getNewPwd());
    }
}
